/*

Copyright (c) 2021 唐佐林
WeChat : delphi_tang
EMail: delphi_tang@dt4sw.com

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

#include "IPCEndPoint.h"

IPCEndPoint::IPCEndPoint(QObject* parent) : QObject(parent), m_handler(NULL)
{
    connect(&m_endpoint, SIGNAL(readyRead()), this, SLOT(onDataReady()));
    connect(&m_endpoint, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onStateChanged(QAbstractSocket::SocketState)));
    connect(&m_endpoint, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)));
}

bool IPCEndPoint::bind(int port)
{
    bool ret = isValid();

    if( !ret )
    {
        ret = m_endpoint.bind(QHostAddress::Any, port);
    }

    return ret;
}

qint64 IPCEndPoint::send(const IPCMessage& message, QString ip, int port)
{
    qint64 ret = -1;

    if( isValid() )
    {
        QByteArray ba = message.serialize();

        ret = m_endpoint.writeDatagram(ba.data(), ba.length(), QHostAddress(ip), port);

        m_endpoint.flush();
    }

    return ret;
}

qint64 IPCEndPoint::available()
{
    qint64 ret = -1;

    if( isValid() )
    {
        ret = m_endpoint.bytesAvailable();
    }

    return ret;
}

void IPCEndPoint::close()
{
    if( isValid() )
    {
        m_endpoint.close();
    }
}

bool IPCEndPoint::isValid()
{
    return (m_endpoint.state() == QAbstractSocket::BoundState);
}

void IPCEndPoint::setHandler(IPCMsgHandler* handler)
{
    m_handler = handler;
}

void IPCEndPoint::onDataReady()
{
    static int s_size = 256;
    static char* s_buf = new char[s_size];

    while( m_endpoint.hasPendingDatagrams() )
    {
        QSharedPointer<IPCMessage> ptm = NULL;
        qint64 len = m_endpoint.pendingDatagramSize();

        if( len > s_size )
        {
            s_size = len;

            delete[] s_buf;

            s_buf = new char[s_size];
        }

        len = m_endpoint.readDatagram(s_buf, s_size);

        m_assembler.prepare(s_buf, len);

        while( (ptm = m_assembler.assemble()) != NULL )
        {
            if( m_handler != NULL )
            {
                m_handler->handle(m_endpoint, *ptm);
            }
        }
    }
}

void IPCEndPoint::onBytesWritten(qint64 bytes)
{
    (void)bytes;
}

void IPCEndPoint::onStateChanged(QAbstractSocket::SocketState state)
{
    (void)state;
}
